<?php
require_once("nusoap/nusoap.php");
require_once('vi_utils.php');
require_once('vi_supportclasses.php');
require_once('vi_sessionmanager.php');
require_once('vi_propertycollector.php');


class vi_ServiceContent
{
    public $viewManager;
    public $setting;
    public $userDirectory;
    public $authorizationManager;
    public $perfManager;
    public $scheduledTaskManager;
    public $alarmManager;
    public $eventManager;
    public $taskManager;
    public $extensionManager;
    public $customizationSpecManager;
    public $customFieldsManager;
    public $diagnosticManager;
    public $licenseManager;
    public $searchIndex;
    public $fileManager;
    public $virtualDiskManager;

    public function __construct($service, $serviceContent)
    {
        $this->viewManager = $serviceContent['viewManager'];
        $this->setting = $serviceContent['setting'];
        $this->userDirectory = $serviceContent['userDirectory'];
        $this->authorizationManager = $serviceContent['authorizationManager'];
        $this->perfManager = $serviceContent['perfManager'];
        $this->scheduledTaskManager = $serviceContent['scheduledTaskManager'];
        $this->alarmManager = $serviceContent['alarmManager'];
        $this->eventManager = $serviceContent['eventManager'];
        $this->taskManager = $serviceContent['taskManager'];
        $this->extensionManager = $serviceContent['extensionManager'];
        $this->customizationSpecManager = $serviceContent['customizationSpecManager'];
        $this->customFieldsManager = $serviceContent['customFieldsManager'];
        $this->diagnosticManager = $serviceContent['diagnosticManager'];
        $this->licenseManager = $serviceContent['licenseManager'];
        $this->searchIndex = $serviceContent['searchIndex'];
        $this->fileManager = $serviceContent['fileManager'];
        $this->virtualDiskManager = $serviceContent['virtualDiskManager'];
    }
}


class visvc
{
    public $sessionManager, $propertyCollector;
    public $rootFolder;
    public $conn;
    private $namespace;
    public $services;

    public $errorMessage = false;


    public function __construct($url)
    {
        $this->conn = new nusoap_client($url);
        $err = $this->conn->getError();
        if ($err !== false)
            throw new Exception($err);

        $this->conn->operation = '';
        $this->namespace = 'urn:vim25';

        $msg = new vi_Message('RetrieveServiceContent');
        $obj = new vic_ManagedObjectReference('ServiceInstance', 'ServiceInstance');

        $result = $this->call($msg, $obj);
        if ($result === false)
            throw new Exception('Unable to retrieve service content.');

        $this->rootFolder = vic_ManagedObjectReference::Folder($result['rootFolder']);
        $this->sessionManager = new vi_SessionManager($this, $result['sessionManager']);
        $this->propertyCollector = new vi_PropertyCollector($this, $result['propertyCollector']);
        $this->services = new vi_ServiceContent($this, $result);
    }


    //
    // Call the given method name with the message data.
    // Returns call result if successful or false if an error occurred.
    // If an error then $this->errorMessage contains the
    // error message returned by the server.
    //
    public function call($msg, $_this = false)
    {
        if (!is_object($msg) || is_a($msg, 'vic_Base') == false)
            throw new Exception('$msg must be of type vic_Base. $msg = "' . $msg . '"');

        $text = $msg->serialize('', $_this, array('xmlns' => $this->namespace));
        $text = $this->conn->serializeEnvelope($text);
        $result = $this->conn->send($text, $this->conn->endpoint);
        if ($result === false)
            throw new Exception('Server responded with error.' . $this->conn->getError());

        $this->errorMessage = '';
        if (isset($result['faultstring']))
        {
            if ($result['faultstring'] == '')
            {
                ob_start();
                var_dump($result['detail']);
                $this->errorMessage = ob_get_clean();
            }
            else
                $this->errorMessage = $result['faultstring'];

            return false;
        }
        else if (isset($result['returnval']))
            return $result['returnval'];
        else
            return null;
    }


    public function GetSessionID()
    {
        foreach ($this->conn->cookies as $k => $v)
        {
            if ($v['name'] == 'vmware_soap_session')
                return str_replace('"', '', $v['value']);
        }

        return null;
    }


    public function SetSessionID($sessionid)
    {
        $cookie = array(
                'name' => 'vmware_soap_session',
                'value' => '"' . $sessionid . '"',
                'domain' => '',
                'path' => '/',
                'expires' => '',
                'secure' => '');
        $this->conn->updateCookies(array($cookie));
    }


    //
    // This function is used by the various List...() functions to parse
    // the results of type ManagedObjectReference with, optionally, values.
    //
    private function ParseManagedObjectResult($type, $result)
    {
        $type = 'vic_ManagedObjectReference::' . $type;
        $items = array();

        if (is_assoc($result))
        {
            if (isset($result['propSet']))
                $properties = vi_PropertyCollector::ConvertProperties($result['propSet']);
            else
                $properties = array();
            $items[] = call_user_func($type, $result['obj'], $properties);
        }
        else
        {
            foreach ($result as $k => $v)
            {
                if (isset($v['propSet']))
                    $properties = vi_PropertyCollector::ConvertProperties($v['propSet']);
                else
                    $properties = array();
                $items[] = call_user_func($type, $v['obj'], $properties);
            }
        }

        return $items;
    }


    public function ListDatacenters($properties = array())
    {
        $propSet = new vic_PropertySpec('Datacenter', 0, $properties);
        $objectSet = new vic_ObjectSpec($this->rootFolder, 0,
                                        vic_TraversalSpec::deepFolderTraversalSpecs());
        $filter = new vic_PropertyFilterSpec($objectSet, $propSet);

        $result = $this->propertyCollector->RetrieveProperties($filter);
        if (!is_array($result))
            throw new Exception("Unable to retrieve list of datacenters (" . $this->errorMessage . ").");

        return $this->ParseManagedObjectResult('Datacenter', $result);
    }


    public function ListClusters($parent = null, $properties = array())
    {
        $propSet = new vic_PropertySpec('ClusterComputeResource', 0, $properties);
        $objectSet = new vic_ObjectSpec(($parent !== null ? $parent : $this->rootFolder), 0,
                                        vic_TraversalSpec::deepFolderTraversalSpecs());
        $filter = new vic_PropertyFilterSpec($objectSet, $propSet);

        $result = $this->propertyCollector->RetrieveProperties($filter);
        if (!is_array($result))
            throw new Exception("Unable to retrieve list of clusters (" . $this->errorMessage . ").");

        return $this->ParseManagedObjectResult('ClusterComputeResource', $result);
    }


    public function ListHosts($parent = null, $properties = array())
    {
        $propSet = new vic_PropertySpec('HostSystem', 0, $properties);
        $objectSet = new vic_ObjectSpec(($parent !== null ? $parent : $this->rootFolder), 0,
                                        vic_TraversalSpec::deepFolderTraversalSpecs());
        $filter = new vic_PropertyFilterSpec($objectSet, $propSet);

        $result = $this->propertyCollector->RetrieveProperties($filter);
        if (!is_array($result))
            throw new Exception("Unable to retrieve list of hosts (" . $this->errorMessage . ").");

        return $this->ParseManagedObjectResult('HostSystem', $result);
    }


    public function ListVirtualMachines($parent = null, $properties = array())
    {
        $propSet = new vic_PropertySpec('VirtualMachine', 0, $properties);
        $objectSet = new vic_ObjectSpec(($parent !== null ? $parent : $this->rootFolder), 0,
                                        vic_TraversalSpec::deepFolderTraversalSpecs());
        $filter = new vic_PropertyFilterSpec($objectSet, $propSet);

        $result = $this->propertyCollector->RetrieveProperties($filter);

        if (!is_array($result))
            throw new Exception("Unable to retrieve list of virtual machines (" . $this->errorMessage . ").");

        return $this->ParseManagedObjectResult('VirtualMachine', $result);
    }


    public function GetObjectProperties($obj, $props = array())
    {
        $propSet = new vic_PropertySpec($obj->GetType(), 0, $props);
        $objectSet = new vic_ObjectSpec($obj, 0);
        $filter = new vic_PropertyFilterSpec($objectSet, $propSet);

        $result = $this->propertyCollector->RetrieveProperties($filter);
        if (!is_array($result) || !isset($result['propSet']))
            throw new Exception("Unable to retrieve object properties (" . $this->errorMessage . ").");

        return vi_PropertyCollector::ConvertProperties($result['propSet']);
    }
}


?>
